﻿#region
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Y2M.Components;
using Y2M.Properties;
using YoutubeExtractor;

#endregion

namespace Y2M.Controls
{
    public partial class DownloadControl : UserControl
    {
        public DownloadControl()
        {
            InitializeComponent();
        }

        private DownloadInfo _downloadInfo;

        public bool DownloadCompledted { get; private set; }

        private WorkerArgument _workerArgument;

        public string OriginalUrl { get; set; }

        public void AddItem(DownloadInfo downloadInfo)
        {
            _downloadInfo = downloadInfo;
            lblTitle.Text = downloadInfo.Title;

            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += Worker_DoWork;
            worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
            worker.RunWorkerAsync(downloadInfo);
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            prbProgress.Visible = false;

            // 멀티플 다운로드 시 e.Result에서 WorkerArgument를 읽으면 마지막 다운로드한 비디오의 값만 읽는 버그가 있음. BackgroundWorker의 버그로 추정됨
//            WorkerArgument workerArgument = (WorkerArgument) e.Result;
            lklTitle.Size = prbProgress.Size;
            lklTitle.Location = prbProgress.Location;
            lklTitle.Visible = true;
            lklTitle.Tag = _workerArgument;
            lklTitle.Text = _workerArgument.DownloadInfo.Title;
            tlpTitle.SetToolTip(lklTitle, _workerArgument.FilePath);
            lklTitle.Visible = true;
            
            lblTitle.Font = new Font(lblTitle.Font, FontStyle.Bold | FontStyle.Strikeout);

            DownloadCompledted = true;


            DownloadingList.Instance.Remove(OriginalUrl);
        }

        private void lklTitle_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            WorkerArgument workerArgument = (WorkerArgument)((LinkLabel)sender).Tag;
            Process.Start(workerArgument.FilePath);
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            DownloadInfo downloadInfo = (DownloadInfo)e.Argument;

            string videoPath = Path.Combine(
                                        Settings.Default.DownloadRoot, 
                                        downloadInfo.ClipInfo.Title + downloadInfo.ClipInfo.VideoExtension);

            var videoDownloader = new VideoDownloader(downloadInfo.ClipInfo.VideoInfo, videoPath);
            videoDownloader.DownloadProgressChanged += VideoDownloader_DownloadProgressChanged;
            videoDownloader.Execute();

            _workerArgument = new WorkerArgument(downloadInfo, videoPath);

            if (_downloadInfo.AudioOnly)
            {
                string audioPath = Path.Combine(
                                        Settings.Default.DownloadRoot,
                                        downloadInfo.Title + ".mp3");

                string argument = string.Format(@"-i ""{0}"" -vn -f mp3 ""{1}""", videoPath, audioPath);

                Process process = new Process();
                process.StartInfo = new ProcessStartInfo("ffmpeg.exe", argument);
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.CreateNoWindow = true;
                process.Start();
                process.WaitForExit();

                File.Delete(videoPath);

                _workerArgument.FilePath = audioPath;
            }

//            e.Result = workerArgument;
        }

        private void VideoDownloader_DownloadProgressChanged(object sender, ProgressEventArgs e)
        {
            prbProgress.InvokeIfNeeded(() => prbProgress.Value = (int)e.ProgressPercentage);
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            OnCloseButtonClicked(_downloadInfo);
        }

        #region CloseButtonClicked event things for C# 3.0
        public event EventHandler<CloseButtonClickedEventArgs> CloseButtonClicked;

        protected virtual void OnCloseButtonClicked(CloseButtonClickedEventArgs e)
        {
            if (CloseButtonClicked != null)
                CloseButtonClicked(this, e);
        }

        protected virtual void OnCloseButtonClicked(DownloadInfo downloadInfo)
        {
            OnCloseButtonClicked(new CloseButtonClickedEventArgs(downloadInfo));
        }

        protected virtual CloseButtonClickedEventArgs OnCloseButtonClickedWithReturn(DownloadInfo downloadInfo)
        {
            CloseButtonClickedEventArgs args = new CloseButtonClickedEventArgs(downloadInfo);
            OnCloseButtonClicked(args);

            return args;
        }

        public class CloseButtonClickedEventArgs : EventArgs
        {
            public DownloadInfo DownloadInfo { get; set; }

            public CloseButtonClickedEventArgs()
            {
            }

            public CloseButtonClickedEventArgs(DownloadInfo downloadInfo)
            {
                DownloadInfo = downloadInfo;
            }
        }
        #endregion

        private class WorkerArgument
        {
            public DownloadInfo DownloadInfo { get; private set; }
            
            public string FilePath { get; set; }

            public WorkerArgument(DownloadInfo downloadInfo, string filePath)
            {
                DownloadInfo = downloadInfo;
                FilePath = filePath;
            }

            public override string ToString()
            {
                return DownloadInfo.Title;
            }
        }
    }
}